package case18

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"net/http"
	"time"
)

func Test() {
	fmt.Println("🎯示例十八：定义中间件(1.全局路由注册2.某个路由单独注册3.路由组注册中间件)")

	/*// 💡为全局路由注册
	// 新建一个没有任何默认中间件的路由
	r := gin.New()
	// 注册一个全局中间件
	r.Use(StatCost())

	r.GET("/test", func(c *gin.Context) {
		name := c.MustGet("name").(string) // 从上下文取值
		c.JSON(http.StatusOK, gin.H{
			"message": "Hello world! , name=" + name,
		})
	})
	r.Run(":60000")*/

	/*// 💡为某个路由单独注册
	// 新建一个没有任何默认中间件的路由
	r := gin.New()

	r.GET("/test2", StatCost(), func(c *gin.Context) {
		name := c.MustGet("name").(string) // 从上下文取值
		c.JSON(http.StatusOK, gin.H{
			"message": "Hello world! , name=" + name,
		})
	})

	r.GET("/test1", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "test1",
		})
	})

	r.Run(":60000")*/

	// 💡为路由组注册中间件
	// 新建一个没有任何默认中间件的路由
	r := gin.New()

	// 为路由组注册中间件有以下两种写法。

	// 方式1
	userGroup := r.Group("/user", StatCost())
	{
		userGroup.GET("/list", func(c *gin.Context) { c.JSON(200, gin.H{"message": "/user/list"}) })
		userGroup.GET("/one", func(c *gin.Context) { c.JSON(200, gin.H{"message": "/user/one"}) })

	}

	// 方式2
	shopGroup := r.Group("/shop")
	shopGroup.Use(StatCost())
	{
		shopGroup.GET("/list", func(c *gin.Context) { c.JSON(200, gin.H{"message": "/shop/list"}) })
		shopGroup.GET("/one", func(c *gin.Context) { c.JSON(200, gin.H{"message": "/shop/one"}) })
	}

	r.GET("/test1", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "test1",
		})
	})

	r.Run(":60000")

	/*中间件注意事项
	gin默认中间件
	gin.Default()默认使用了Logger和Recovery中间件，其中：

	💡Logger中间件将日志写入gin.DefaultWriter，即使配置了GIN_MODE=release。
	💡Recovery中间件会recover任何panic。如果有panic的话，会写入500响应码。
	如果不想使用上面两个默认的中间件，💡可以使用gin.New()新建一个没有任何默认中间件的路由。

	gin中间件中使用goroutine
	当在中间件或handler中启动新的goroutine时，不能使用原始的上下文（c *gin.Context），必须使用其只读副本（c.Copy()）。*/

}

// Gin中的中间件必须是一个gin.HandlerFunc类型。

// StatCost 是一个统计耗时请求耗时的中间件
func StatCost() gin.HandlerFunc {
	return func(c *gin.Context) {

		start := time.Now()
		c.Set("name", "小王子") // 可以通过c.Set在请求上下文中设置值，后续的处理函数能够取到该值
		// 调用该请求的剩余处理程序
		c.Next()
		// 不调用该请求的剩余处理程序
		// c.Abort()
		// 计算耗时
		cost := time.Since(start)
		log.Printf("请求地址：%s , 耗时：%v", c.Request.URL.Path, cost)
	}
}
